package com.smart.nine.spel.summary.spelcompiler;

import com.smart.nine.spel.summary.User;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.SpelCompilerMode;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * 编译器测试
 *
 * @author junrui.wang
 * @create 2019/3/20
 */
public class CompilerSample {
    public static void main(String[] args) {
        //编译器适用于表达式重复调用频率高的场景
        User user1 = new User("Tom", 100);

        //创建解析配置
        SpelParserConfiguration configuration = new SpelParserConfiguration(
                //编译模式
                //SpelCompilerMode.OFF 默认不开启
                //SpelCompilerMode.MIXED 混合 先解释型，达到阈值（100）之后使用编译型
                //SpelCompilerMode.IMMEDIATE 立即启用编译。SpEl中不会立即使用，当第二次执行表达式获取取值时才会启用编译
                SpelCompilerMode.MIXED,
                //类加载器
                CompilerSample.class.getClassLoader());
        //创建解析器
        SpelExpressionParser expressionParser = new SpelExpressionParser(configuration);
        //创建取值上下文
        EvaluationContext context1 = new StandardEvaluationContext(user1);

        //创建表达式
        String expression = "isVipMember('Tom') && isVipMember(getName())";
        //使用编译器
        Expression spElExpression = expressionParser.parseRaw(expression);

        //第一次调用
        System.out.println(spElExpression.getValue(context1));
        //第二次调用
        System.out.println(spElExpression.getValue(context1));


        long beginTime = System.currentTimeMillis();
        for (int i=0; i<1000000000; i++) {
            //通过表达式求值
            spElExpression.getValue(context1);
        }
        long endTime = System.currentTimeMillis();
        System.out.println(endTime-beginTime);

        /*
            测试结果：
            OFF: >100000
            MIXED:24853
            IMMEDIATE:19111
         */


    }
}
